################# store global function ################

function(print_var name)
    # 打印输出
    message(WARNING ${name})
endfunction()

################# 需要增加子模块的编译方法，否则容易冲突 ############
######## 比如把cuda自模块编译成静态，然后链接到对外开放的dll中 ########

##################### 编译常规静态子模块 ##########################
function(SegSubModuleBuild
         project_name
         source_list
         target_link)

    add_library(${project_name} STATIC ${source_list})
    if(${target_link})
        target_link_libraries(${PROJECT_NAME} PRIVATE ${target_link})
    endif()
endfunction()


###################  编译静态cuda子模块 #######################
function(SegCudaModuleBuild
         project_name
         source_list
         need_link_other_cuda
         target_link)

    add_library(${project_name} STATIC ${source_list})

    if (${need_link_other_cuda})
        set_target_properties(${project_name}
                PROPERTIES
                CUDA_SEPARABLE_COMPILATION ON  # cu will build by nvcc
                POSITION_INDEPENDENT_CODE ON  # for split __device__ into multi *.a
                CUDA_RESOLVE_DEVICE_SYMBOLS ON # ask for relink symbol
                LINKER_LANGUAGE CXX
        )
    else()
        set_target_properties(${project_name}
                PROPERTIES
                CUDA_SEPARABLE_COMPILATION ON  # cu will build by nvcc
                POSITION_INDEPENDENT_CODE ON  # for split __device__ into multi *.a
                LINKER_LANGUAGE CXX
        )
    endif()

    if(${target_link})
        target_link_libraries(${PROJECT_NAME} PRIVATE ${target_link})
    endif()
endfunction()

###################  编译主流程 #######################
function(SegModuleMainBuild
         project_name
         source_list
         source_dir
         public_header_list
         build_for_py
         target_link)

    if(${build_for_py})
        pybind11_add_module(${project_name} ${source_list})
    else()
        add_library(${project_name} SHARED ${source_list})
    endif()

    target_include_directories(${project_name}
            INTERFACE
            $<BUILD_INTERFACE:${source_dir}>
            $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
    )

    set_target_properties(${project_name}
            PROPERTIES
                PUBLIC_HEADER ${public_header_list}
                LINKER_LANGUAGE CXX
    )

    install(
            TARGETS ${project_name}
            EXPORT ${project_name}Targets
            PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
            RUNTIME DESTINATION bin
            LIBRARY DESTINATION lib
            ARCHIVE DESTINATION lib
    )

    install(
            EXPORT ${project_name}Targets
            FILE ${project_name}Targets.cmake
            DESTINATION ${CMAKE_INSTALL_DATADIR}/${project_name}/cmake
            NAMESPACE ${project_name}::
    )

    configure_package_config_file(
            ${CMAKE_SOURCE_DIR}/cmake/templates/NeedOpenCV.cmake.in
            ${CMAKE_CURRENT_BINARY_DIR}/${project_name}Config.cmake
            INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/${project_name}/cmake
    )

    install(
            FILES ${CMAKE_CURRENT_BINARY_DIR}/${project_name}Config.cmake
            DESTINATION ${CMAKE_INSTALL_DATADIR}/${project_name}/cmake
    )

    if(${target_link})
        target_link_libraries(${PROJECT_NAME} PRIVATE ${target_link})
    endif()
endfunction()

################################## 旧的编译主流程，保留 ########################
function(SegModuleBuild
        project_name
        source_list
        source_dir
        public_header_list
        build_for_py
        build_for_shared
        need_link_other_cuda)

    # project_name: module name
    # source_list: header, src, wrapper or test
    # source_dir: source abs path
    # public_header_list: which header to install
    # build_for_py: use pybind11_add_module or add_library

    if(${build_for_py})
        pybind11_add_module(${project_name} ${source_list})
    elseif(${build_for_shared})
        add_library(${project_name} SHARED ${source_list})
    else()
        add_library(${project_name} STATIC ${source_list})
#        target_compile_features(${project_name} PUBLIC cuda_std_14)
    endif()

    target_include_directories(${project_name}
            INTERFACE
            $<BUILD_INTERFACE:${source_dir}>
            $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
    )

    if (${need_link_other_cuda})
        set_target_properties(${project_name}
            PROPERTIES
                PUBLIC_HEADER ${public_header_list}
                CUDA_SEPARABLE_COMPILATION ON  # cu will build by nvcc
                POSITION_INDEPENDENT_CODE ON  # for split __device__ into multi *.a
                CUDA_RESOLVE_DEVICE_SYMBOLS ON # ask for relink symbol
                LINKER_LANGUAGE CXX
        )
    else()
        set_target_properties(${project_name}
            PROPERTIES
                PUBLIC_HEADER ${public_header_list}
                CUDA_SEPARABLE_COMPILATION ON  # cu will build by nvcc
                POSITION_INDEPENDENT_CODE ON  # for split __device__ into multi *.a
                LINKER_LANGUAGE CXX
        )
    endif()



    install(
            TARGETS ${project_name}
            EXPORT ${project_name}Targets
            PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
            RUNTIME DESTINATION bin
            LIBRARY DESTINATION lib
            ARCHIVE DESTINATION lib
    )

    install(
            EXPORT ${project_name}Targets
            FILE ${project_name}Targets.cmake
            DESTINATION ${CMAKE_INSTALL_DATADIR}/${project_name}/cmake
            NAMESPACE ${project_name}::
    )

    configure_package_config_file(
            ${CMAKE_SOURCE_DIR}/cmake/templates/NeedOpenCV.cmake.in
            ${CMAKE_CURRENT_BINARY_DIR}/${project_name}Config.cmake
            INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/${project_name}/cmake
    )

    install(
            FILES ${CMAKE_CURRENT_BINARY_DIR}/${project_name}Config.cmake
            DESTINATION ${CMAKE_INSTALL_DATADIR}/${project_name}/cmake
    )


endfunction()